package synchronize.synchronize004;

/**
 * 脏读的例子
 * 业务整体需要使用完整的synchronized，保持业务的原子性
 */
public class DirtyRead {
    private String username = "bjsxt";
    private String password = "123";

    /**
     * 脏读的例子
     * 设置用户名，等待2秒后设置密码，最后打印参数中的用户名和密码
     *
     * @param username
     * @param password
     */
    public synchronized void setValue(String username, String password) {
        System.out.println("开始赋值username");
        this.username = username;
        System.out.println("赋值username结束");
        try {
            System.out.println("开始等待两秒");
            Thread.sleep(2000);
            System.out.println("等待两秒结束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("开始赋值password");
        this.password = password;
        System.out.println("赋值password结束");
        System.out.println("setValue最终结果:username=" + username + ",password=" + password);
    }

    /**
     * 打印当前实体成员变量的用户名和密码
     */
    public synchronized void getValue() {
        System.out.println("getValue方法得到:username=" + this.username + ",password=" + this.password);
    }

    /**
     * 脏读的例子
     * 第一个线程：主线程
     * 第二个线程：t1
     * 如果此方法没有getValue没有synchronized就会有脏读的情况，因为主线程休眠1秒后直接输出getValue，setValue需要休眠2秒。
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        final DirtyRead dr = new DirtyRead();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("开始调用setValue方法");
                dr.setValue("z3", "456");
                System.out.println("调用setValue方法结束");
            }
        });
        t1.start();
        System.out.println("开始等待一秒");
        Thread.sleep(1000);
        System.out.println("等待一秒结束");
        dr.getValue();
    }
}
